# -*- coding: UTF-8 -*-
import RPi.GPIO as GPIO
import socket
import threading
from time import sleep

import HydraulicGauge as HG
import FormatLogger

# 启用日志
if __name__ == "__main__":
    logger = FormatLogger.FormatLogger()

serviceState = False
hgValue = 5  # 预设值  当水压大于值启动水泵开始采样,反之停止水泵


class GPIOService:
    # 功能对象
    functionWaterPump = "水泵"
    # 功能对应引脚
    pinWaterPump = 4

    @staticmethod
    def initGPIOService():  # 初始化引脚
        # BCM编码
        GPIO.setmode(GPIO.BCM)
        # 4号引脚控制蠕动泵相连继电器 默认输出高电平以关闭继电器
        GPIO.setup(GPIOService.pinWaterPump, GPIO.OUT, initial=GPIO.HIGH)
        logger.logInfo("引脚初始化完成")

    @staticmethod
    def stopGPIOService():
        GPIO.cleanup()
        logger.logWarn("GPIO服务已终止")

    @staticmethod
    def startWaterPump():  # 启动水泵
        GPIO.output(GPIOService.pinWaterPump, GPIO.LOW)

    @staticmethod
    def stopWaterPump():  # 停止水泵
        GPIO.output(GPIOService.pinWaterPump, GPIO.HIGH)


class RemoteService(threading.Thread):
    # 连接设备列表 用于多个终端可同时控制无人船
    __connList = []

    def __init__(self, ip="", port=55435):
        threading.Thread.__init__(self)
        self.__ipAddress = (ip, port)
        self.__serviceSocket = socket.socket()
        self.__serviceSocket.bind(self.__ipAddress)
        self.__serviceSocket.listen(5)
        logger.logInfo("套接字服务已启动...等待终端连接")
        self.start()

    def listenConn(self):
        while True:
            conn, address = self.__serviceSocket.accept()
            connService = ConnectionService(conn, address)
            self.updateConn()
            self.__connList.append(connService)

    # 更新连接设备列表
    def updateConn(self):
        for conn in self.__connList:
            if not conn.isAlive():
                self.__connList.remove(conn)

    def run(self):
        self.listenConn()
        self.__serviceSocket.close()
        logger.logWarn("套接字服务已终止")


class ConnectionService(threading.Thread):

    # 指令集
    ACTION_START_SERVICE = "0"
    ACTION_STOP_SERVICE = "1"

    ACTION_SET_HGVALUE = "9"

    def __init__(self, conn, address):
        threading.Thread.__init__(self)
        self.__conn = conn
        self.__address = address
        self.__state = 1
        logger.logWarn("["+self.__address[0]+":"+str(self.__address[1])+"]终端已连接")
        self.start()

    def listenConn(self):
        while True:
            try:
                # 接受数据报
                command = self.__conn.recv(16)
                self.excuseCommand(str(command, encoding='utf-8'))
            except ConnectionResetError:
                logger.logWarn("["+self.__address[0]+":"+str(self.__address[1])+"]终端终止了连接")
                break

    def isAlive(self):
        return self.__state

    def excuseCommand(self, command):
        global serviceState
        global hgValue
        if command:
            if command[0] == self.ACTION_START_SERVICE:
                serviceState = True
                logger.logCommand("[" + self.__address[0] + ":" + str(self.__address[1]) + "]启动服务")
            elif command[0] == self.ACTION_STOP_SERVICE:
                serviceState = False
                logger.logCommand("[" + self.__address[0] + ":" + str(self.__address[1]) + "]停止服务")
            elif command[0] == self.ACTION_SET_HGVALUE:
                commandStr = command[1:].strip()
                hgValue = int(commandStr)
                logger.logCommand("[" + self.__address[0] + ":" + str(self.__address[1]) + "]设置水压值" + commandStr)
            else:
                logger.logWarn("[" + self.__address[0] + ":" + str(self.__address[1]) + "]未知指令" + command)
        else:
            self.__conn.close()
            logger.logWarn("[" + self.__address[0] + ":" + str(self.__address[1]) + "]终端终止了连接")

    def run(self):
        self.listenConn()


def autoSampling():
    if HG.openSerial():
        logger.logInfo("水压计工作正常")
        while True:
            if serviceState:
                data = HG.readData()
                if data >= 0:
                    if data >= hgValue:  # 超过预设水压启动水泵
                        GPIOService.startWaterPump()
                    else:
                        GPIOService.stopWaterPump()
                sleep(0.2)  # 暂未处理数据丢失问题
            else:
                sleep(1)
    else:
        logger.logErr("水压计运行错误")


if __name__ == "__main__":
    # 初始化引脚
    GPIOService.initGPIOService()
    # 启动远程服务
    remoteService = RemoteService()
    # 开启自动采样
    autoSampling()
